﻿// Base class for the form fields to manipulate the names, values and enabled of the fields, track changes and set the focus
define([
    'Wjs/ui/elements/View',
    'Wjs/ui/elements/mixins/Valuable',
    'Wjs/ui/elements/mixins/ValueWatcher',
    'Wjs/ui/elements/mixins/Validatable',
    'Wjs/ui/elements/mixins/Disableable',
    'Wjs/data/types/string'
],
function () {
    'use strict';

    return Wjs.defineOnce({

        type: 'FieldBase',

        internal: {

            base: Wjs.getType('View'),

            mixins: [
                Wjs.getType('Valuable'),
                Wjs.getType('ValueWatcher'),
                Wjs.getType('Validatable'),
                Wjs.getType('Disableable')
            ],

            initialize: function () {

                this.addClass('wjs-field');
            }
        },

        // Sets the name of the field
        setName: function (name) {

            if (!name) {

                throw Error('Name of the field is required');
            }

            this.setAttribute('name', name);

            return this;
        },

        // Sets the data type to convert to when extracting the value from the field.
        // Defaults to string
        // TODO: Replace it by a type converter ???
        setDataType: function (dataType) {

            if (!Wjs.isDefined(dataType)) { // Default to string

                this.dataType = Wjs.getType('string', true /*throwIfNotFound*/);
            }
            else if (Wjs.isString(dataType)) { // Get the type fron the string

                this.dataType = Wjs.getType(dataType, true /*throwIfNotFound*/);
            }
            else { // Pass the object

                this.dataType = dataType;
            }

            return this;
        },

        //#region Event handlers

        onInput: function (fcn) {

            return this.onDomEvent('input', fcn);
        },

        onChange: function (fcn) {

            return this.onDomEvent('change', fcn);
        },     

        onFocus: function (fcn) {
            
            return this.onDomEvent('focus', fcn);
        },

        onBlur: function (fcn) {
        
            return this.onDomEvent('blur', fcn);
        },

        onKeyUp: function (fcn) {
          
            return this.onDomEvent('keyup', fcn);
        },

        onKeyDown: function (fcn) {
            
            return this.onDomEvent('keydown', fcn);
        },

        onKeyPress: function (fcn) {

            return this.onDomEvent('keypress', fcn);
        },

        //#endregion

        //#region Default event handlers

        //changeHandler: function(evt) {

        //    //this.fireFieldChanged(evt);
        //},

        blurHandler: function (evt) {

            var form = this.getForm(),
                validationContext = form.validationContext;

            // Some validation can be triggered on the blur event
            this.validate(validationContext, true /* validateOnBlur */);

            if (validationContext.validationSummary &&
                validationContext.errors.length) {

                Wjs.validationSummary.setErrors(validationContext.errors);
                Wjs.validationSummary.show();
            }

            validationContext.errors.length = 0; // Reset the errors
        },

        keyPressHandler: function (evt) {

            this.restrictInput(evt);
        },

        //#endregion

        getForm: function () {

            if (!this.form) {

                this.form = this.up(function (parent) {

                    return parent instanceof Wjs.getType('Form');
                });
            }

            return this.form;
        },

        // Gets the name of the field
        getName: function () {

            return this.getAttribute('name');
        },

        valueSetHandler: function (options) {
            var me = this;

            options = options || {};

            if (options.acceptChanges) {

                me.acceptChanges();
            }

            if (options.fireFieldChanged !== false) { // Fires the field changed event by default

                me.fireFieldChanged();
            }
        },

        setFocus: function () {

            if (this.isRendered()) {

                this.domEl.focus();
            }
            else {

                throw 'setFocus - Element must be rendered.'
            }

            return this;
        }
    });

});